<?php

namespace app\service;

//use app\model\AppBenefitLevel;
//use app\model\AppBenefitOrder;
//use app\model\AppCommissionConfig;
//use app\model\AppFund;
//use app\model\AppLog;
//use app\model\AppUser;
//use app\model\AppUserBenefit;
//use app\model\AppUserBenefitLog;
//use app\model\AppUserMoney;
//use app\model\AppUserScore;
//use app\model\AppUserWithdraw;
//use Carbon\Carbon;

use app\model\BenefitLevel;
use app\model\User;
use app\model\UserBenefit;

class DailyJobService
{
    public function release(): void
    {
        $benefits = UserBenefit::
        where('user_id in ' . User::where('status', 'on')
                ->field('id')
                ->buildSql(true)
        )->
        where('remain_benefit', '>', 0)
//            ->select();
            ->cursor();
        foreach ($benefits as $benefit) {
            $benefit->release();
        }
//        sdump(round(memory_get_peak_usage(true) / 1024.0 / 1024, 2) . 'MB');
    }

    public function levelup()
    {
        $levels = BenefitLevel::order('id')->select();
        foreach ($levels as $level) {
            User::where('benefit_level_id', $level->id - 1)
                ->with('children')
                ->chunk(100, function ($users) use ($level, $levels) {
                    foreach ($users as $user) {dd(1);
                        $performance      = $user->performance;
                        $performances     = $user->children->map(function ($child) {
                            return $child->performance + $child->spending;
                        });
                        $maxPerformance   = $performances->count() > 1 ? max(...$performances->toArray()) : ($performances->first() ?? 0);
                        $otherPerformance = $performance - $maxPerformance;

//                        $otherPerformance = $otherPerformance < 0 ? 0 : $otherPerformance;
                        $children_count   = $user->children->where('benefit_level_id', '>=', $level->id - 1)->count();
//                       if($user->id == 331){
//                            var_dump($children_count);die;
//                       }
                        if ( $user->performance >= $level->total_performance
                            && $maxPerformance >= $level->main_performance
                            && $otherPerformance >= $level->other_performance
                            && $children_count >= $level->children_count) {
                            $user->levelup_time     = Carbon::now()->toDateTimeString();
                            $user->benefit_level_id = $level->id;
                            $user->save();
                        }
                    }
                });
        }
//        sdump(round(memory_get_peak_usage(true) / 1024.0 / 1024, 2) . 'MB');
    }

    public function clearBenefitOrder()
    {
        AppBenefitOrder::where('create_time', '<', Carbon::now()->addDays(-1)->format('Y-m-d H:i:s'))
            ->where('status', 'paying')
            ->delete();
    }

    /**
     */
    public function speedupRelease(): void
    {
//        $users       = AppUser::cursor();
        AppUser::where('status', 'on')->with([
            'children' => function (/** @var AppUser $query */ $query) {
                $query->with([ 'benefit' => function (/** @var AppUserBenefit $query */ $query) { $query->remain(); } ]);
            },
            'puser'    => function (/** @var AppUser $query */ $query) {
                $query->with([ 'remained_benefit', 'puser.remained_benefit' ]);
            },
            'remained_benefit',
        ])->chunk(100, function ($users) {
            $rate        = AppCommissionConfig::getConfigValue('benefit_release_rate') / 100;
            $speedupRate = AppCommissionConfig::getConfigValue('benefit_speedup_rate') / 100;
            /** @var AppUser $user */
            foreach ($users as $user) {
                $speedups = [];
                foreach ($user->children as $child) {
                    foreach ($child->benefit as $item) {
                        $childSpeed = $item->principal * $item->that_proportion * $speedupRate;
//                        var_dump($childSpeed);die;
                        $speedups[] = [ 'benefit' => $childSpeed, 'item' => $item ];
//                        AppUserBenefit::speedup($user, $childSpeed, 'speedup', 'direct', $item);
                    }
                }
                if ($user->remained_benefit->count() == 0) {
//                    sdump('oldId: ' . $user->id);
                    $user = $user->puser;
                    if (!$user) {
                        continue;
                    }
//                    sdump('newId: ' . $user->id);
                    if ($user->remained_benefit->count() == 0) {
//                        sdump('oldId1: ' . $user->id);
                        $user = $user->puser;
                        if (!$user) {
                            continue;
                        }
//                        sdump('newId1: ' . $user->id);
                    }
                }
                AppUserBenefit::speedupMany($user, $speedups);
            }
        });
        sdump(round(memory_get_peak_usage(true) / 1024.0 / 1024, 2) . 'MB');
    }



    /**
     * @throws
     */
    public function teamRelease(): void
    {
        $rate = AppCommissionConfig::getConfigValue('benefit_release_rate') / 100;
        // 查出所有用户
        // 计算用户释放
        $users  = AppUser::where('status', 'on')->withSum([
            'benefit' => function ($query, &$alias) {
                $query->where('remain_benefit', '>', 0);
                $alias = 'everyday_release';
            },
        ], 'principal * that_proportion')
            ->withSum([
                'children' => function ($query, &$alias) use ($rate) {
                    $subSql = $query->withSum([
                        'benefit' => function ($query, &$alias) {
                            $query->where('remain_benefit', '>', 0);
                            $alias = 'everyday_release';
                        },
                    ], 'principal * that_proportion' )->buildSql(true);
                    $query->table($subSql);
                    $alias = 'children_release';
                },
            ], 'everyday_release')
            ->with([ 'remained_benefit' ])
            ->select();
        $levels = AppBenefitLevel::select();
        // 查找自己的下级的释放
        // 查找用户团队
        // 查找自己的团队释放 = 自己的下级释放 + 自己的下级的团队释放
        foreach ($users as $user) {
            // 用引用的方式减少内存占用
            $user->benefit_level = $levels->first(function ($item) use ($user) { return $item->id == $user->benefit_level_id; });
        }
        foreach ($users as $user) {
            // 用引用的方式减少内存占用
            $user->team = AppUser::getTeamPerformance($user->id, $users);
//            $user->children = $user->getPerformanceChildren();
            $user->children = $users->where('pid', $user->id);
        }
        foreach ($users as $user) {
            if ($user->getData('benefit_level')) {
//                sdump($user->benefit_level);
                $user->teamup = $user->getTeamRelease();
            }
        }
//        dd($users->map(fn($i)=> count($i->team)));
        // 执行团队释放
        foreach ($users as $user) {
            if (!$user->teamup) {
                continue;
            }
            AppUserBenefit::speedup($user, $user->teamup, 'speedup', 'team');
        }
        sdump(round(memory_get_peak_usage(true) / 1024.0 / 1024, 2) . 'MB');
    }



    public function releaseFund()
    {
        AppUser::withSum([
            'benefit_log' => function (/** @var AppUserBenefitLog $query */ $query, &$alias) {
                $query->where('TO_DAYS(create_time)=TO_DAYS(NOW())');
                $query->where(['type'=>'everyday']);
                $alias = 'today_benefit';
            },
        ], 'benefit')
            ->having('today_benefit>0')->chunk(100, function ($users) {
                /** @var AppUser $user */
                foreach ($users as $user) {
                    AppFund::createFundByCompositionType('release', $user->today_benefit, $user->id);
                }
            });

    }

    public function createAppLog()
    {
        $time       = now()->addDays(-1);
        $dateString = $time->toDateString();
        $data       = [
            'user'           => AppUser::where("TO_DAYS(create_time)=TO_DAYS('$dateString')")->count(),
            'benefit_order'  => AppBenefitOrder::where("TO_DAYS(pay_time)=TO_DAYS('$dateString')")->count(),
            'benefit_amount' => AppBenefitOrder::where("TO_DAYS(pay_time)=TO_DAYS('$dateString')")->sum('pay_amount'),
            'gold_income'    => AppUserBenefitLog::where("TO_DAYS(create_time)=TO_DAYS('$dateString')")->sum('benefit'),
            'gold_release'   => AppUserBenefitLog::where("TO_DAYS(create_time)=TO_DAYS('$dateString')")->sum('benefit'),
            'money_income'   => AppUserMoney::where("TO_DAYS(create_time)=TO_DAYS('$dateString')")->whereIn('wallet_type', [
                'charge',
                'admin_charge',
                'trans',
                'commission',
                'exchange',
            ])->sum('wallet'),
            'money_withdraw' => AppUserWithdraw::where("TO_DAYS(update_time)=TO_DAYS('$dateString')")->where('state', 'success')->sum('withdraw_money'),
            'money_expend'   => AppUserMoney::where("TO_DAYS(create_time)=TO_DAYS('$dateString')")->whereIn('wallet_type', [ 'expense' ])->sum('wallet'),
            'money_remain'   => AppUser::sum('money'),
            //    add type enum ('sign', 'good', 'expend', 'back', 'exchange', 'commission', 'admin', 'benefit') default 'sign' not null comment '签到,返回,支出,退款,兑换（旧商城）,管理员充值,释放';
            'score_income'   => AppUserScore::where("TO_DAYS(create_time)=TO_DAYS('$dateString')")->whereIn('type', [
                'sign',
                'exchange',
                'commission',
                'admin',
                'benefit',
            ])->sum('score'),
            'score_expend'   => AppUserScore::where("TO_DAYS(create_time)=TO_DAYS('$dateString')")->whereIn('type', [ 'expend' ])->sum('score'),
            'score_remain'   => AppUser::sum('score'),
        ];
        $log        = new AppLog();
        $log->replace(true)->save([
            'date' => $time->toDateString(),
            'log'  => $data,
        ]);
    }
}
